﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Skyhook.Core
{
    public class Camera
    {
        Rectangle View;
        Point Center;
        Rectangle Bound;

        public delegate void PositionChangeEvent(Point centerposition,Point lefttopposition);
    
        private bool IsPositionValid(int newx, int newy)
        {
            Rectangle newview = new Rectangle(newx - View.Width / 2, newy - View.Height / 2, View.Width, View.Height);
            if (!Bound.Contains(newview))
            {
                return false;
            }

            return true;
        }

        private void UpdateCenterPoint(int newx, int newy)
        {
            if (IsPositionValid(newx, newy))
            {
                Center.X = newx;
                Center.Y = newy;
                View.X = Center.X - View.Width / 2;
                View.Y = Center.Y - View.Height / 2;
                ExecuteOnCenterPointChange();
            }
        }

        private void ExecuteOnCenterPointChange()
        {
            if (OnCenterPointChange != null)
            {
                OnCenterPointChange(Center,new Point(Left,Top));
            }
        }

        private void ValidateBoundAndView(Rectangle bound, int viewwidth, int viewheight)
        {
            if (bound.Width <= 0 || bound.Height <= 0)
            {
                throw new Exception("Incorrect camera bound : (" + bound.X + "," + bound.Y + "," + bound.Width + "," + bound.Height + ")");
            }

            if (viewwidth <= 0 || viewheight <= 0)
            {
                throw new Exception("Incorrect camera view size : (" + viewwidth + "," + viewheight + ")");
            }
        }

        public Camera(Rectangle bound, int viewwidth, int viewheight)
        {
            ValidateBoundAndView(bound,viewwidth,viewheight);

            Bound = bound;
            View = new Rectangle(0, 0, viewwidth, viewheight);
            Center = new Point(0, 0);
            UpdateCenterPoint(Bound.Width / 2, Bound.Height / 2);
        }

        public void Put(int x, int y)
        {
            UpdateCenterPoint(x, y);
        }

        public void Move(int dx, int dy)
        {
            UpdateCenterPoint(Center.X + dx, Center.Y + dy);
        }

        public int X
        {
            get
            {
                return Center.X;
            }
        }

        public int Y
        {
            get
            {
                return Center.Y;
            }
        }

        public int Left
        {
            get
            {
                return View.X;
            }
        }

        public int Top
        {
            get
            {
                return View.Y;
            }
        }

        public void AddListener(ICameraListener listener)
        {
            OnCenterPointChange += listener.OnCameraChange;
        }

        public void RemoveListener(ICameraListener listener)
        {
            OnCenterPointChange -= listener.OnCameraChange;
        }

        event PositionChangeEvent OnCenterPointChange;
    }
}
